﻿using Domain;
using Domain.Entity;
using Domain.Event;
using Domain.ValueObject;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace Infrastructure
{
    public class UserRepository : IUserDomainRepository
    {
        private readonly UserContext dbCtx;
        private readonly IDistributedCache distCache;
        private readonly IMediator mediator;

        public UserRepository(UserContext dbCtx, IDistributedCache distCache, IMediator mediator)
        {
            this.dbCtx = dbCtx;
            this.distCache = distCache;
            this.mediator = mediator;
        }

        public async Task AddNewLoginHistoryAsync(PhoneNumber phone, string msg)
        {
            User? user = await FindOneAsync(phone);
            UserLoginHistory loginHistory = new UserLoginHistory(user.Id, phone, msg);
            dbCtx.UserLoginHistories.Add(loginHistory);
            //未进行SaveChange(); 一般不在Repository中进行SaveChange处理，而是放在应用层
        }

        public async Task<User?> FindOneAsync(PhoneNumber phone)
        {
            return await dbCtx.Users.Include(u => u.AccessFail).FirstOrDefaultAsync(m => m.Phone.Number == phone.Number && m.Phone.RegionCode == phone.RegionCode);

        }

        public async Task<User?> FindOneAsync(Guid guid)
        {
            return await dbCtx.Users.Include(u => u.AccessFail).FirstOrDefaultAsync(u => u.Id == guid);
        }

        public async Task SavePhoneCodeAsync(PhoneNumber phone, string code)
        {
            var options = new DistributedCacheEntryOptions();
            options.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(120);
            await distCache.SetStringAsync($"{phone.RegionCode}_{phone.Number}", code, options);
        }

        public async Task<string?> GetCodeByPhoneAsync(PhoneNumber phone)
        {
            return await distCache.GetStringAsync($"{phone.RegionCode}_{phone.Number}");
        }

        public async Task PublishEventAsync(UserAccessResultEvent eventData)
        {
            await mediator.Publish(eventData);           
        }


    }
}
